import React, { useEffect, useState, Key } from 'react'
import {
  Button,
  Form,
  Input,
  Space,
  Card,
  Table,
  Tooltip,
  Modal,
  message,
} from 'antd'
import {
  SearchOutlined,
  EditOutlined,
  DeleteOutlined,
  ExclamationCircleOutlined,
} from '@ant-design/icons'
import type { ColumnsType } from 'antd/es/table'

import { useNavigate } from 'react-router-dom'

//引入发送请求的函数
import {
  reqGetHospitalSets,
  reqDelOneHospitalSet,
  reqBatchDelHospitalSets,
} from '@api/hospitalSet'

// 引入ts
import {
  IhospitalsetList,
  IhospitalsetItem,
} from '@api/hospitalSet/model/hospitalSetTypes'

// flag的作用是用来标记用户是否点击了查询按钮.true为点击了,false为未点击
let flag = false
export default function HospitalSet() {
  const navigate = useNavigate()
  // 创建form实例
  const [form] = Form.useForm()
  // 注意: 在基于ts的环境下,如果useState的初始值是空数组,则状态数据的类型自动推论为never[]
  // 注意: useState也可以通过泛型的方式,来描述创建出来的状态是什么类型
  const [hospitalSets, setHospitalSets] = useState<IhospitalsetList>([])

  // 数据总数的状态
  const [total, setTotal] = useState(0)
  // 一页几条的状态
  const [pageSize, setPageSize] = useState(5)
  // 控制页码高亮的状态
  const [page, setPage] = useState(1)

  // 存储批量删除id的数组
  const [ids, setIds] = useState<string[]>([])

  // 展示正在加载效果
  const [loading, setLoading] = useState(false)

  async function getHospitalSets(
    page: number,
    pageSize: number,
    hosname?: string,
    hoscode?: string
  ) {
    setLoading(true)
    const result = await reqGetHospitalSets(page, pageSize, hosname, hoscode)
    // console.log(result.records)
    setHospitalSets(result.records)
    setTotal(result.total)
    setLoading(false)
  }
  // 注意: 模拟挂载的回调,不允许定义为异步函数
  useEffect(() => {
    getHospitalSets(1, pageSize)
  }, [])

  // 查询按钮的事件处理函数
  const onFinish = (values: any) => {
    // console.log('Success:', values)

    // 将flag改为true,表示用户已经点击了查询按钮
    flag = true

    // 解构values,获取到hosname和hoscode
    const { hosname, hoscode } = values
    // 发送请求获取表格中的筛选数据
    getHospitalSets(1, pageSize, hosname, hoscode)

    // 让页码1高亮
    setPage(1)
  }

  // 清空按钮的事件处理函数
  const clearForm = () => {
    // 0. 将flag设置为false
    flag = false
    // 1. 清空表单
    form.setFieldsValue({ hosname: '', hoscode: '' })
    // 2. 不添加筛选条件的情况下请求表格数据
    getHospitalSets(1, pageSize)
    setPage(1)
  }

  // 注意: 定义columns数据时,columns的类型是ColumnsType.但是再描述columns类型时,必须通过泛型传入dataSource接收的数据数组中的对象的类型
  const columns: ColumnsType<IhospitalsetItem> = [
    {
      title: '序号', // 控制当前列的标题
      // dataIndex的作用也分为两种情况:
      // 1. 写了render函数,则dataIndex决定了render函数中第一个参数的值
      // 2. 不写render函数,则dataIndex决定了这一列渲染什么
      // dataIndex: 'address',
      // key: 'name', // key是当前这一列的唯一标识符,但是可以不写
      // 如果写了render函数,则render函数的返回值决定了这一列渲染什么内容
      render: (a, b, c) => {
        // console.log(a, b, c)
        // 第一个参数a: 的值不固定,分为两种情况:
        // 1. 没写dataIndex的时候,第一个参数和第二个参数一样,都是数据对象
        // 2. 写了dataIndex,dataIndex的值是dataSource中数据对象的属性.那么第一个参数就是这个属性的值
        // 第二个参数b: 永远固定为dataSource这个数据中对应的数据对象
        // 第三个参数c: 永远是数据对象在dataSource数组中的下标
        return c + 1
      },

      align: 'center', // 让这一列的文本水平居中
    },
    {
      title: '医院名称',
      dataIndex: 'hosname',
    },
    {
      title: '医院编码',
      dataIndex: 'hoscode',
    },
    {
      title: 'api基础路径',
      dataIndex: 'apiUrl',
    },
    {
      title: '签名',
      dataIndex: 'signKey',
    },
    {
      title: '联系人名称',
      dataIndex: 'contactsName',
    },
    {
      title: '联系人手机号',
      dataIndex: 'contactsPhone',
    },
    {
      title: '操作',
      dataIndex: 'id',
      render(id) {
        return (
          <Space>
            {/* 鼠标移动到Button上方,Tooltip会在Button上方出现提示文本 */}
            <Tooltip title="修改医院">
              <Button
                type="primary"
                icon={<EditOutlined />}
                onClick={() => {
                  navigate(`/syt/hospital/hospitalset/update/${id}`)
                }}
              ></Button>
            </Tooltip>
            <Tooltip title="删除医院">
              <Button
                type="primary"
                danger
                icon={<DeleteOutlined />}
                onClick={() => {
                  Modal.confirm({
                    title: '您确定要删除这个医院吗',
                    icon: <ExclamationCircleOutlined />,
                    // content: 'Some descriptions',
                    okText: '确认',
                    okType: 'danger', // 按钮为红色
                    cancelText: '取消',
                    async onOk() {
                      // 发送请求,删除数据
                      await reqDelOneHospitalSet(id)
                      message.success('医院删除成功')
                      if (flag) {
                        const { hosname, hoscode } = form.getFieldsValue()
                        getHospitalSets(page, pageSize, hosname, hoscode)
                      } else {
                        getHospitalSets(page, pageSize)
                      }
                    },
                  })
                }}
              ></Button>
            </Tooltip>
          </Space>
        )
      },
      width: 100, // 控制这一列的宽度
      fixed: 'right', //当前列在右侧固定
    },
  ]

  return (
    // Card组件拥有白色背景颜色和内边距
    <Card>
      <Form
        form={form}
        // layout属性用来控制表单中的表单元素布局方式
        layout="inline"
        name="basic" // 表单的名称
        // antd中默认支持栅格系统.一行24列.
        // labelCol是指表单元素的描述文本部分
        // wrapperCol是值表单元素部分
        // span表示当前部分一行中占多少份
        // labelCol={{ span: 8 }}
        // wrapperCol={{ span: 16 }}
        // initialValues用来设置表单中表单元素的初始值
        // remember是某个Form.Item组件的name属性的值.这个name属性就代表了这个表单元素
        initialValues={{ remember: false }}
        // 当用户点击了表单元素的提交按钮,表单会默认进行表单校验.如果校验通过,则触发onFinish.如果表单校验触发,会触发onFinishFailed

        // 如果没有表单校验,则只要点击了提交按钮,就会触发onFinish.此时onFinishFailed就没有用了
        onFinish={onFinish}
        // onFinishFailed={onFinishFailed}
        autoComplete="off"
        onValuesChange={(changedValues, allValues) => {
          // console.log(changedValues, allValues)\
          // 只要用户在表单中输入,flag设置为false .强制要求用户每次输入完之后都必须点击查询
          flag = false
        }}
      >
        {/* Form.Item用于包裹表单元素 */}
        <Form.Item
          // label="Username" // label是表单元素的描述文本
          name="hosname" //name的值用来控制当前的表单元素(相当于就是表单元素的name属性)
          // 当前表单元素的校验规则
          // rules={[
          //   {
          //     // required: true 表示当前表单元素必填
          //     required: true,
          //     // 表单校验不通过是的提示文本
          //     message: 'Please input your username!',
          //   },
          // ]}
        >
          {/* 注意: 这个Input是antd中的组件.但是最终渲染的还是文本框 */}
          <Input placeholder="医院名称" />
        </Form.Item>

        <Form.Item
          // label="Password"
          name="hoscode"
          // rules={[{ required: true, message: 'Please input your password!' }]}
        >
          {/* 这是密码框 */}
          {/* <Input.Password /> */}
          <Input placeholder="医院编码" />
        </Form.Item>

        {/* <Form.Item
          name="remember"
          valuePropName="checked"
          // offset表示当前表单元素在栅格系统中偏移8份的位置
          wrapperCol={{ offset: 8, span: 16 }}
        > */}
        {/* Checkbox 是antd的组件,代表html中的复选框 */}
        {/* <Checkbox>Remember me</Checkbox>
        </Form.Item> */}

        <Form.Item>
          {/* 注意: 并不是写在Form表单中的Button都是提交按钮.只有写了htmlType="submit"的Button才是当前表单的提交按钮 */}
          <Space>
            <Button type="primary" htmlType="submit" icon={<SearchOutlined />}>
              查询
            </Button>
            <Button onClick={clearForm}>清空</Button>
          </Space>
        </Form.Item>
      </Form>
      {/* Space为包裹的组件添加间隔 */}
      <Space style={{ marginTop: 20, marginBottom: 20 }}>
        <Button
          type="primary"
          onClick={() => {
            navigate('/syt/hospital/hospitalset/add')
          }}
        >
          添加
        </Button>
        <Button
          type="primary"
          danger
          disabled={!ids.length}
          onClick={async () => {
            Modal.confirm({
              title: '您确定要删除这些医院吗',
              icon: <ExclamationCircleOutlined />,
              // content: 'Some descriptions',
              okText: '确认',
              okType: 'danger', // 按钮为红色
              cancelText: '取消',
              async onOk() {
                // 发送请求,删除数据
                await reqBatchDelHospitalSets(ids)
                setIds([]) // 清空数组,禁用批量删除按钮
                message.success('医院批量删除成功')
                if (flag) {
                  const { hosname, hoscode } = form.getFieldsValue()
                  getHospitalSets(page, pageSize, hosname, hoscode)
                } else {
                  getHospitalSets(page, pageSize)
                }
              },
            })
          }}
        >
          批量删除
        </Button>
      </Space>

      {/*  
        columns决定了Table组件中有多少列
        dataSource 决定了Table组件中有多少行(条)数据
        scroll={{x:1500}}  让表格支持滚动. x代表是水平方向滚动. 1500是x的值单位是px
        1500代表了可滚动的距离

        bordered 让表格中显示边框
        */}
      <Table
        loading={loading}
        columns={columns}
        dataSource={hospitalSets}
        scroll={{ x: 1500 }}
        bordered
        // 告诉Table,去找每一条数据对象的id作为列表渲染时的key值
        rowKey="id"
        pagination={{
          current: page, // 用来控制哪个页码高亮
          total, // 数据总数
          // 注意: pageSize决定了选择一页几条下拉框的值
          pageSize, // 一页几条. pagination会根据total/pageSize计算出来应该有几页
          showSizeChanger: true, // 展示选择一页几条的下拉框
          pageSizeOptions: [2, 5, 10], //决定了一页几条的下拉框里的选项
          showQuickJumper: true, // 展示快速跳转的控件
          showTotal(total) {
            // 在分页器前方展示信息
            // console.log(total) // 这个total的值来源于配置项total
            return `总共: ${total}` //返回值是什么,则分页器前面展示什么
          },
          // 当页码变化,或pageSize变化都会触发
          onChange(page, pageSize) {
            // page 是用户选择的页码
            // pageSize 是用户选择的一页几条
            // console.log(page, pageSize)
            setPageSize(pageSize)
            setPage(page)

            // 判断,有些时候要加上hosname和hoscode,有些时候不用加hosname和hoscode
            if (flag) {
              // 获取表单中的hosname和hoscode,然后将筛选条件添加到getHospitalSets中
              const { hosname, hoscode } = form.getFieldsValue()

              getHospitalSets(page, pageSize, hosname, hoscode)
            } else {
              getHospitalSets(page, pageSize)
            }
          },
        }}
        rowSelection={{
          onChange(ids) {
            setIds(ids as string[])
          },
        }}
      />
    </Card>
  )
}
